﻿using System.Text;
using LDM.Framework.Application;
using LDM.Framework.NormalizeActionResult;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using LDM.Framework.JwtBearer.Filters;
using Model;

namespace LDM.Framework;

/// <summary>
/// JwtBearer服务扩展类
/// </summary>
public static class JwtBearerServiceCollectionExtensions
{
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="builder"></param>
    /// <param name="jwtBearerConfigure"></param>
    /// <returns></returns>
    private static AuthenticationBuilder AddJwt(this AuthenticationBuilder builder, Action<JwtBearerOptions>? jwtBearerConfigure)
    {
        builder.AddJwtBearer(options =>
        {
            var audience = App.Configuration.GetSection("Jwt:Audience").Value.ToString();
            options.TokenValidationParameters = new TokenValidationParameters
            {
                //是否验证签发者
                ValidateIssuer = true,
                //是否验证接受者
                ValidateAudience = true,
                //是否验证签名密钥
                ValidateIssuerSigningKey = true,
                ////验证令牌过期时间
                ValidateLifetime = true,
                //令牌安全时是否保存令牌
                SaveSigninToken = true,
                //签发者
                ValidAudience = App.Configuration.GetSection("Jwt:Audience").Value.ToString(),//订阅者
                                                                                              //接受者 订阅者
                ValidIssuer = App.Configuration.GetSection("Jwt:Issuer").Value.ToString(),//Issuer，这两项和前面签发jwt的设置一致
                                                                                          //签名密钥
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(App.Configuration.GetSection("Jwt:SecurityKey").Value.ToString())),//密钥
                                                                                                                                                      //令牌过期时间的偏移值
                ClockSkew = TimeSpan.FromMinutes(60)
            };

            jwtBearerConfigure?.Invoke(options);
        });

        return builder;
    }


    /// <summary>
    /// 添加Bearer认证
    /// </summary>
    /// <param name="services"></param>
    /// <param name="authenticationConfigure"></param>
    /// <param name="jwtBearerConfigure"></param>
    /// <returns></returns>
    public static IServiceCollection AddJwtWithBearerAuthentication(this IServiceCollection services)
    {
        services.AddJwtWithBearerAuthentication(null, options =>
         {
             options.Events = new JwtBearerEvents()
             {
                 OnChallenge = context =>
                 {
                     context.HandleResponse();
                     context.Response.Clear();
                     context.Response.ContentType = "application/json";
                     context.Response.StatusCode = 401;
                     var result = ResultData.ValidateError("认证未通过", null);
                     context.Response.WriteAsync(JsonConvert.SerializeObject(result, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }));
                     return Task.CompletedTask;
                 }
             };
         });
        services.AddSessionFilter();
        return services;
    }




    /// <summary>
    /// 添加Bearer认证
    /// </summary>
    /// <param name="services"></param>
    /// <param name="authenticationConfigure"></param>
    /// <param name="jwtBearerConfigure"></param>
    /// <returns></returns>
    public static IServiceCollection AddJwtWithBearerAuthentication(this IServiceCollection services,
        Action<AuthenticationOptions>? authenticationConfigure = null,
        Action<JwtBearerOptions>? jwtBearerConfigure = null)
    {
        //添加认证相关服务并配置认证方案
        var authenticationBuilder = services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            authenticationConfigure?.Invoke(options);
        });
        //添加Bearer认证
        authenticationBuilder.AddJwt(jwtBearerConfigure);

        return services;
    }


    /// <summary>
    /// 添加Session解析
    /// </summary>
    /// <param name="services"></param>
    /// <param name="authenticationConfigure"></param>
    /// <param name="jwtBearerConfigure"></param>
    /// <returns></returns>
    public static IServiceCollection AddSessionFilter(this IServiceCollection services)
    {
        //注册用户会话,用户解析token存储用户信息
        services.AddScoped<Session>()
        .AddControllers(options =>
        {
            //获取请求用户信息
            options.Filters.Add<AsyncSessionFilter>();
        });
        return services;
    }
}
